package pl.smath.renderer.model;

import gwt.g2d.client.graphics.Surface;

import com.google.gwt.user.client.ui.RootPanel;

import pl.smath.renderer.model.sign.DivisionSign;
import pl.smath.renderer.renderer.TermRendererException;
import pl.smath.renderer.utils.Cursor;
import pl.smath.renderer.utils.InteractionSocket;
import pl.smath.renderer.utils.Rectangle;

public class DivisionView extends AbstractMultiView {

	private DivisionSign divisionSign;
	
	public DivisionView() {
		super(":");
		divisionSign = new DivisionSign();
	}
	
	/**
	 * render text at the current position
	 * @param canvas
	 */
	@Override
	public void render(Surface canvas, InteractionSocket socket) throws TermRendererException {
		if ((this.getFont() == null)||(this.getFontHeight() == null)) {
			throw new TermRendererException();
		}
		canvas.setFont(this.getFont());
		
		Cursor cursor = new Cursor(this.getCursor().getX(), this.getCursor().getY() - this.getBaselineOffset());
		
		Double signWidth = this.divisionSign.getWidth();
		Double minusWidth = this.minusSign.getWidth();
		Double rightBracketWidth = canvas.measureText(")");
		
		if (this.isNegative()) {
			this.minusSign.render(canvas, cursor);
			cursor.setX(cursor.getX() + minusWidth);
		}
		
		for (int i = 0; i < this.views.size(); i++) {
			View view = this.views.elementAt(i);

			if ((i > 0)&&(!(view instanceof VariableView))) {
				this.divisionSign.render(canvas, cursor);
				cursor.setX(cursor.getX() + signWidth);
			}
			
			if(view instanceof SumView) {
				canvas.fillText("(", cursor.getX(), cursor.getY());
			}
			
			view.render(canvas, socket);
			cursor.setX(view.getX() + view.getWidth());

			if(view instanceof SumView) {
				canvas.fillText(")", cursor.getX(), cursor.getY());
				cursor.setX(cursor.getX() + rightBracketWidth);
			}
		}
	}
	

	/**
	 * set the position on canvas to render
	 * @param Cursor
	 */
	@Override
	public void setCursor(Cursor cursor) {
		//if (this.getCursor()==null) {
			super.setCursor(new Cursor(cursor.getX(), cursor.getY()));
			
			Surface canvas = new Surface();
			RootPanel.get().add(canvas);
			canvas.setFont(this.getFont());
			
			Double signWidth = this.divisionSign.getWidth();
			Double leftBracketWidth = canvas.measureText("(");
			Double rightBracketWidth = canvas.measureText(")");
			Double minusWidth = this.minusSign.getWidth();
			
			Cursor toSet = new Cursor(cursor.getX(), cursor.getY() - this.getBaselineOffset());
			if (this.isNegative()) toSet.setX(toSet.getX() + minusWidth);
			
			for (int i = 0; i < this.views.size(); i++) {
				View view = this.views.elementAt(i);
				
				if ((i > 0)&&(!(view instanceof VariableView))) toSet.setX(toSet.getX() + signWidth);
				
				if(view instanceof SumView) {
					toSet.setX(toSet.getX() + leftBracketWidth);
					view.setCursor(new Cursor(toSet.getX(), toSet.getY() + view.getBaselineOffset()));
					toSet.setX(toSet.getX() + rightBracketWidth);
				} else if (view instanceof FractionView) { 
					Double cursorY = toSet.getY() + ((FractionView) view).getDenominator().getHeight() - this.getFontHeight()/2 + FractionView.getSpace();
					view.setCursor(new Cursor(toSet.getX(), cursorY));
				} else {
					view.setCursor(new Cursor(toSet.getX(), toSet.getY() + view.getBaselineOffset()));
				}
				
				toSet.setX(toSet.getX() + view.getWidth());
			} 

			RootPanel.get().remove(canvas);

		/*} else {
			Double deltaX = cursor.getX() - this.getX();
			Double deltaY = cursor.getY() - this.getY();
			for (View view : this.views) {
				view.setX(view.getX() + deltaX);
				view.setY(view.getY() + deltaY);
			}
			super.setCursor(cursor);
		}*/
		
	}
	
	/**
	 * @param font the font to set
	 */
	@Override
	public void setFont(String font) {
		if (font.indexOf("px")!=-1) {
			this.setFontHeight(new Double(font.substring(0, font.indexOf("px"))));
			this.font = font.substring(font.indexOf("px ")+3);
			this.minusSign.setFont(this.font, this.getFontHeight());
			this.divisionSign.setFont(this.font, this.getFontHeight());
			this.divisionSign.setSpace(this.getFontHeight() * 0.2d);

			for (View view : this.views) {
				view.setFont(font);
			}
			
			update();
		} else {
			this.setFontHeight(null);
			this.font = null;
		}
	}
	
	/**
	 * updates the view after changes
	 */
	@Override
	public void update() {
		Surface surface = new Surface();
		RootPanel.get().add(surface);
		surface.setFont(this.getFont());
		
		Double signWidth = this.divisionSign.getWidth();
		Double bracketsWidth = surface.measureText("()");
		Double minusWidth = this.minusSign.getWidth();
		Double maxOverBaseline = 0d;
		
		this.setRectangle(new Rectangle());
		
		for (int i = 0; i < this.views.size(); i++) {
			View view = this.views.elementAt(i);
			this.setWidth(this.getWidth() + view.getWidth());
			
			if ((i > 0)&&(!(view instanceof VariableView))) this.setWidth(this.getWidth() + signWidth);
			
			if(view instanceof SumView) this.setWidth(this.getWidth() + bracketsWidth);
			
			Double overBaseline = 0d;
			
			if (view instanceof FractionView) {
				Double baselineOffset = ((FractionView) view).getDenominator().getHeight() - this.getFontHeight()/2 + FractionView.getSpace();
				overBaseline = view.getHeight() - baselineOffset;
				this.setBaselineOffset(Math.max(this.getBaselineOffset(), baselineOffset));			
			} else {
				this.setBaselineOffset(Math.max(this.getBaselineOffset(), view.getBaselineOffset()));
				overBaseline = view.getHeight() - view.getBaselineOffset();
			}
			maxOverBaseline = Math.max(maxOverBaseline, overBaseline);
		}
		
		this.setHeight(maxOverBaseline + this.getBaselineOffset());
		
		
		if(this.isNegative())
			this.setWidth(this.getWidth() + minusWidth);

		RootPanel.get().remove(surface);
	}

}
